package com.maple.service.impl;

import com.maple.dto.GoodsSalesDTO;
import com.maple.entity.Orders;
import com.maple.mapper.OrderMapper;
import com.maple.mapper.UserMapper;
import com.maple.service.ReportService;
import com.maple.service.WorkSpaceService;
import com.maple.vo.*;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.poi.util.StringUtil;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;


@Service
public class ReportServiceImpl implements ReportService {



    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private WorkSpaceService workSpaceService;

    /**
     * 订单统计
     * @param begin
     * @param end
     * @return
     */
    @Override
    public OrderReportVO ordersStatistics(LocalDate begin, LocalDate end) {
//        封装三个list集合对象
        List<LocalDate> timeList = getTimeList(begin, end);
        List<Integer> totalOrderCountList = new ArrayList<>();
        List<Integer> validOrderCountList  = new ArrayList<>();

//        遍历日期集合并查询数据库，封装每日订单总数list与有效订单数list
        for(LocalDate time : timeList){
            LocalDateTime timeMin = LocalDateTime.of(time, LocalTime.MIN);
            LocalDateTime timeMax = LocalDateTime.of(time, LocalTime.MAX);
//            获得每日总的订单数
            totalOrderCountList.add(orderMapper.getOrderCountByTimesAndStatus(timeMin, timeMax, null));
//            获得每日总的有效订单数
            validOrderCountList.add(orderMapper.getOrderCountByTimesAndStatus(timeMin, timeMax, Orders.COMPLETED));
        }

//        封装总的订单总数与有效订单数与订单完成率
        Integer totalOrderCount = totalOrderCountList.stream().mapToInt(Integer::intValue).sum();
        Integer validOrderCount = validOrderCountList.stream().mapToInt(Integer::intValue).sum();

        Double orderCompletionRate = 0.0;
        if(totalOrderCount != 0){
            orderCompletionRate = validOrderCount.doubleValue() / totalOrderCount;
        }

//       返回 三个list集合的数据处理
        return OrderReportVO.builder()
                .dateList(StringUtil.join(",", timeList))
                .orderCompletionRate(orderCompletionRate)
                .orderCountList(StringUtil.join(",", totalOrderCountList))
                .totalOrderCount(totalOrderCount)
                .validOrderCount(validOrderCount)
                .validOrderCountList(StringUtil.join(",", validOrderCountList))
                .build();
    }

    /**
     * 查询销量排名top10
     * @param begin
     * @param end
     * @return
     */
    @Override
    public SalesTop10ReportVO getTop10(LocalDate begin, LocalDate end) {
//      封装时间对象
        LocalDateTime timeMin = LocalDateTime.of(begin, LocalTime.MIN);
        LocalDateTime timeMax = LocalDateTime.of(end, LocalTime.MAX);

//        查询数据库中的订单表和订单详细表，封装为list<GoodSales>集合（只查询菜品，套餐不要）
        List<GoodsSalesDTO> list = orderMapper.getTop10ByTimes(timeMin, timeMax);

//        数据处理并返回
        List<String> names = list.stream().map(GoodsSalesDTO::getName).toList();
        List<Integer> numbers = list.stream().map(GoodsSalesDTO::getNumber).toList();

        return SalesTop10ReportVO.builder()
                .numberList(StringUtil.join(",", numbers))
                .nameList(StringUtil.join(",", names))
                .build();

    }

    /**
     * 用户统计
     * @param begin
     * @param end
     * @return
     */
    @Override
    public UserReportVO getUserStatistics(LocalDate begin, LocalDate end) {
        List<LocalDate> timeList = getTimeList(begin, end);
        List<Integer> newUserList = new ArrayList<>();
        List<Integer> totalUserList  = new ArrayList<>();

//        遍历日期集合并查询数据库，封装每日订单总数list与有效订单数list
        for(LocalDate time : timeList){
            LocalDateTime timeMin = LocalDateTime.of(time, LocalTime.MIN);
            LocalDateTime timeMax = LocalDateTime.of(time, LocalTime.MAX);
//            获得总的用户数
            totalUserList.add(userMapper.getUserCountByTimes(null, timeMax));
//            获得新增用户数
            newUserList.add(userMapper.getUserCountByTimes(timeMin, timeMax));
        }

//        封装数据并返回
        return UserReportVO.builder()
                .dateList(StringUtil.join(",", timeList))
                .totalUserList(StringUtil.join(",", totalUserList))
                .newUserList(StringUtil.join(",", newUserList))
                .build();

    }

    /**
     * 营业额统计
     * @param begin
     * @param end
     * @return
     */
    @Override
    public TurnoverReportVO getTurnover(LocalDate begin, LocalDate end) {
//        封装对象
        List<LocalDate> timeList = getTimeList(begin, end);
        List<Double> turnoverList = new ArrayList<>();

//        遍历时间集合并进行数据库查询
        for(LocalDate time : timeList){
            LocalDateTime timeMin = LocalDateTime.of(time, LocalTime.MIN);
            LocalDateTime timeMax = LocalDateTime.of(time, LocalTime.MAX);

            turnoverList.add(orderMapper.getTurnoverCount(timeMin ,timeMax));
        }

//        数据处理并返回
        return TurnoverReportVO.builder()
                .dateList(StringUtil.join(",", timeList))
                .turnoverList(StringUtil.join(",", turnoverList))
                .build();
    }

    /**
     * 导出Excel报表
     * @param response
     */
    @Override
    public void exportBusinessData(HttpServletResponse response) {
        //1. 查询数据库，获取营业数据---查询最近30天的运营数据
        LocalDate begin = LocalDate.now().plusDays(-30);
        LocalDate end = LocalDate.now().plusDays(-1);

        BusinessDataVO businessData = workSpaceService.getTodayBusinessData(LocalDateTime.of(begin, LocalTime.MIN),
                LocalDateTime.of(end, LocalTime.MIN));



        try(InputStream in = this.getClass().getClassLoader().getResourceAsStream("templates/运营数据报表模板.xlsx")){
//            获得Excel
            XSSFWorkbook excel = null;
            if (in != null) {
                excel = new XSSFWorkbook(in);
            }

//            获得页面
            XSSFSheet sheet = null;
            if (excel != null) {
                sheet = excel.getSheet("Sheet1");
            }

            //填充数据--时间
            sheet.getRow(1).getCell(1).setCellValue("时间：" + begin + "至" + end);

//            获得概览数据所在行
            XSSFRow row3 = sheet.getRow(3);
            row3.getCell(2).setCellValue(businessData.getTurnover());
            row3.getCell(4).setCellValue(businessData.getOrderCompletionRate());
            row3.getCell(6).setCellValue(businessData.getNewUsers());

            XSSFRow row4 = sheet.getRow(4);
            row4.getCell(2).setCellValue(businessData.getValidOrderCount());
            row4.getCell(4).setCellValue(businessData.getUnitPrice());

//            遍历excel行，填充数据
            LocalDate beginTime = LocalDate.now().plusDays(-30);
            LocalDate endTime = LocalDate.now().plusDays(-30);
            for(int i = 7; endTime.isAfter(end) || endTime.isEqual(end); i++, beginTime = beginTime.plusDays(1), endTime = endTime.plusDays(1)){


                BusinessDataVO business = workSpaceService.getTodayBusinessData(
                        LocalDateTime.of(beginTime, LocalTime.MIN),
                        LocalDateTime.of(endTime, LocalTime.MIN));

                XSSFRow row = sheet.getRow(i);
                row.getCell(1).setCellValue("时间：" + beginTime + "至" + endTime);
                row3.getCell(2).setCellValue(business.getTurnover());
                row4.getCell(3).setCellValue(business.getValidOrderCount());
                row3.getCell(4).setCellValue(business.getOrderCompletionRate());
                row4.getCell(5).setCellValue(business.getUnitPrice());
                row3.getCell(6).setCellValue(business.getNewUsers());

            }

            //3. 通过输出流将Excel文件下载到客户端浏览器
            ServletOutputStream out = response.getOutputStream();
            excel.write(out);

            //关闭资源
            out.close();
            excel.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static List<LocalDate> getTimeList(LocalDate begin, LocalDate end) {
//        封装三个list集合对象
        List<LocalDate> timeList = new ArrayList<>();

//        日期数据封装
        timeList.add(begin);
        while(!begin.isEqual(end)){
            begin = begin.plusDays(1);
            timeList.add(begin);
        }
        timeList.add(end);
        return timeList;
    }


}
